emacs open includes in code files, multiple directories - c

ECB, cscope, xcscope. All working. Is cedet necessary?
MSVS, eclipse, code::blocks, xcode. All of them allow easy click on an included source file and take you to it.
Now, with the above setup, emacs does too.
Except emacs doesn't take you to the std:: libraries, doesn't assume their location in /src/linux or some such. Emacs is a little blind and needs you to manually set it up.
But I can't find anything that explains how to set up ff-find-other-file to search for any other directories, let alone standard major libraries, outside of a project's directory.
So, how do I do it?
Edit; Most important is to be able to request on either a file name (.h, .c, .cpp, .anything) or a library (iostream) and open the file in which the code resides.

Additional directories for ff-find-other-file to look into are in ff-search-directories variable which by default uses the value of cc-search-directories, so you should be able to customize any of the two to specify additional search paths.
As for the second question about requesting a file name and finding corresponding file, something like that will do:
(defun ff-query-find-file (file-name)
(interactive "sFilename: ")
;; dirs expansion is borrowed from `ff-find-the-other-file` function
(setq dirs
(if (symbolp ff-search-directories)
(ff-list-replace-env-vars (symbol-value ff-search-directories))
(ff-list-replace-env-vars ff-search-directories)))
(ff-get-file dirs file-name))
Call it with M-x ff-query-find-file or bind it to a key to your liking.

Related

Automatically find dependencies and create CMakeLists.txt with CMake (or CMake Tools in Visual Studio Code) [duplicate]

CMake offers several ways to specify the source files for a target.
One is to use globbing (documentation), for example:
FILE(GLOB MY_SRCS dir/*)
Another method is to specify each file individually.
Which way is preferred? Globbing seems easy, but I heard it has some downsides.
Full disclosure: I originally preferred the globbing approach for its simplicity, but over the years I have come to recognise that explicitly listing the files is less error-prone for large, multi-developer projects.
Original answer:
The advantages to globbing are:
It's easy to add new files as they
are only listed in one place: on
disk. Not globbing creates
duplication.
Your CMakeLists.txt file will be
shorter. This is a big plus if you
have lots of files. Not globbing
causes you to lose the CMake logic
amongst huge lists of files.
The advantages of using hardcoded file lists are:
CMake will track the dependencies of a new file on disk correctly - if we use
glob then files not globbed first time round when you ran CMake will not get
picked up
You ensure that only files you want are added. Globbing may pick up stray
files that you do not want.
In order to work around the first issue, you can simply "touch" the CMakeLists.txt that does the glob, either by using the touch command or by writing the file with no changes. This will force CMake to re-run and pick up the new file.
To fix the second problem you can organize your code carefully into directories, which is what you probably do anyway. In the worst case, you can use the list(REMOVE_ITEM) command to clean up the globbed list of files:
file(GLOB to_remove file_to_remove.cpp)
list(REMOVE_ITEM list ${to_remove})
The only real situation where this can bite you is if you are using something like git-bisect to try older versions of your code in the same build directory. In that case, you may have to clean and compile more than necessary to ensure you get the right files in the list. This is such a corner case, and one where you already are on your toes, that it isn't really an issue.
The best way to specify sourcefiles in CMake is by listing them explicitly.
The creators of CMake themselves advise not to use globbing.
See: https://cmake.org/cmake/help/latest/command/file.html?highlight=glob#glob
(We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.)
Of course, you might want to know what the downsides are - read on!
When Globbing Fails:
The big disadvantage to globbing is that creating/deleting files won't automatically update the build-system.
If you are the person adding the files, this may seem an acceptable trade-off, however this causes problems for other people building your code, they update the project from version-control, run build, then contact you, complaining that"the build's broken".
To make matters worse, the failure typically gives some linking error which doesn't give any hints to the cause of the problem and time is lost troubleshooting it.
In a project I worked on we started off globbing but got so many complaints when new files were added, that it was enough reason to explicitly list files instead of globbing.
This also breaks common git work-flows(git bisect and switching between feature branches).
So I couldn't recommend this, the problems it causes far outweigh the convenience, when someone can't build your software because of this, they may loose a lot of time to track down the issue or just give up.
And another note, Just remembering to touch CMakeLists.txt isn't always enough, with automated builds that use globbing, I had to run cmake before every build since files might have been added/removed since last building *.
Exceptions to the rule:
There are times where globbing is preferable:
For setting up a CMakeLists.txt files for existing projects that don't use CMake.Its a fast way to get all the source referenced (once the build system's running - replace globbing with explicit file-lists).
When CMake isn't used as the primary build-system, if for example you're using a project who aren't using CMake, and you would like to maintain your own build-system for it.
For any situation where the file list changes so often that it becomes impractical to maintain. In this case it could be useful, but then you have to accept running cmake to generate build-files every time to get a reliable/correct build (which goes against the intention of CMake - the ability to split configuration from building).
* Yes, I could have written a code to compare the tree of files on disk before and after an update, but this is not such a nice workaround and something better left up to the build-system.
In CMake 3.12, the file(GLOB ...) and file(GLOB_RECURSE ...) commands gained a CONFIGURE_DEPENDS option which reruns cmake if the glob's value changes.
As that was the primary disadvantage of globbing for source files, it is now okay to do so:
# Whenever this glob's value changes, cmake will rerun and update the build with the
# new/removed files.
file(GLOB_RECURSE sources CONFIGURE_DEPENDS "*.cpp")
add_executable(my_target ${sources})
However, some people still recommend avoiding globbing for sources. Indeed, the documentation states:
We do not recommend using GLOB to collect a list of source files from your source tree. ... The CONFIGURE_DEPENDS flag may not work reliably on all generators, or if a new generator is added in the future that cannot support it, projects using it will be stuck. Even if CONFIGURE_DEPENDS works reliably, there is still a cost to perform the check on every rebuild.
Personally, I consider the benefits of not having to manually manage the source file list to outweigh the possible drawbacks. If you do have to switch back to manually listed files, this can be easily achieved by just printing the globbed source list and pasting it back in.
You can safely glob (and probably should) at the cost of an additional file to hold the dependencies.
Add functions like these somewhere:
# Compare the new contents with the existing file, if it exists and is the
# same we don't want to trigger a make by changing its timestamp.
function(update_file path content)
set(old_content "")
if(EXISTS "${path}")
file(READ "${path}" old_content)
endif()
if(NOT old_content STREQUAL content)
file(WRITE "${path}" "${content}")
endif()
endfunction(update_file)
# Creates a file called CMakeDeps.cmake next to your CMakeLists.txt with
# the list of dependencies in it - this file should be treated as part of
# CMakeLists.txt (source controlled, etc.).
function(update_deps_file deps)
set(deps_file "CMakeDeps.cmake")
# Normalize the list so it's the same on every machine
list(REMOVE_DUPLICATES deps)
foreach(dep IN LISTS deps)
file(RELATIVE_PATH rel_dep ${CMAKE_CURRENT_SOURCE_DIR} ${dep})
list(APPEND rel_deps ${rel_dep})
endforeach(dep)
list(SORT rel_deps)
# Update the deps file
set(content "# generated by make process\nset(sources ${rel_deps})\n")
update_file(${deps_file} "${content}")
# Include the file so it's tracked as a generation dependency we don't
# need the content.
include(${deps_file})
endfunction(update_deps_file)
And then go globbing:
file(GLOB_RECURSE sources LIST_DIRECTORIES false *.h *.cpp)
update_deps_file("${sources}")
add_executable(test ${sources})
You're still carting around the explicit dependencies (and triggering all the automated builds!) like before, only it's in two files instead of one.
The only change in procedure is after you've created a new file. If you don't glob the workflow is to modify CMakeLists.txt from inside Visual Studio and rebuild, if you do glob you run cmake explicitly - or just touch CMakeLists.txt.
Specify each file individually!
I use a conventional CMakeLists.txt and a python script to update it. I run the python script manually after adding files.
See my answer here:
https://stackoverflow.com/a/48318388/3929196
I'm not a fan of globbing and never used it for my libraries. But recently I've looked a presentation by Robert Schumacher (vcpkg developer) where he recommends to treat all your library sources as separate components (for example, private sources (.cpp), public headers (.h), tests, examples - are all separate components) and use separate folders for all of them (similarly to how we use C++ namespaces for classes). In that case I think globbing makes sense, because it allows you to clearly express this components approach and stimulate other developers to follow it. For example, your library directory structure can be the following:
/include - for public headers
/src - for private headers and sources
/tests - for tests
You obviously want other developers to follow your convention (i.e., place public headers under /include and tests under /tests). file(glob) gives a hint for developers that all files from a directory have the same conceptual meaning and any files placed to this directory matching the regexp will also be treated in the same way (for example, installed during 'make install' if we speak about public headers).

CMake - Getting list of source/header files for various subprojects

Background
I have a large cmake project that makes use of dozens of subprojects: some from in-house code bases, and some third-party projects which also use CMake.
To ensure common compiler options, I setup a macro in CMake called CreateDevFlags which is run in only the in-house sub-projects own CMakeLists file as the first line of code to execute. This makes sure that I don't break the compiler flags, output directory overrides, etc, for third-party projects, and all of the code I wrote myself is built with identical options.
Additionally, each sub project has a simple block of code along the lines of the following to define the source files to be compiled:
file(GLOB subproject_1A_SRC
"src/*.c"
)
file(GLOB subproject_1A_INC
"inc/*.h"
)
file(GLOB subproject_2B_SRC
"src/*.c"
"extra_src/*.c"
)
file(GLOB subproject_2B_INC
"inc/*.h"
"extra_details_inc/*.h"
)
Goal
I would like to add a sanity-check custom rule/function to the "master" CMakeLists file at the project root which runs all of the code for in-house subprojects through a code sanitizer (checks newlines, enforces style rules, etc).
Question
Is there a trivial way to have all "special" (ie: in-house) subprojects append their own source files to a "master" list of source (.c) and header (.h) files (possibly via the macro I created)? I realize I could manually create this list in the master CMakeLists file, but then I'd be duplicating efforts, and code maintainers would have to modify code in two places with this in effect.
Thank you.
One possible implementation would be to have a list called FILE_TRACKER defined at top scope for your project. Then, you could do something like
# Create local list to append to
set(LOCAL_LIST ${FILE_TRACKER})
# Append all of your source files, from your local source
foreach(SRC_FILE ${subproject_1A_SRC})
list(APPEND LOCAL_LIST ${SRC_FILE})
endforeach()
# Append to the upper macro (note: was initially set with FILE_TRACKER)
set(FILE_TRACKER ${LOCAL_LIST} PARENT_SCOPE)
The developers would only have to add their source to the one list, and the macro at the top level will be updated with the files.
In the end. the following approach solved my problem:
set(DIR1_SRCS "file1.cpp" PARENT_SCOPE)
and then in ./CMakeLists.txt
set(SRCS ${DIR1_SRCS} ${DIR2_SRCS})
I suggest you don't examine header files. Instead use include dirs for the paths to the header files. If you do this you will automatically get the depends working without having to track them yourself.
Your sanitizer should be able to parse the actual code to find and read the included headers.

Adding paths to header files in the Linux kernel

which environmental variable indicates the list of all the directories which are searched in order to find out the header file included in a C file in the Linux kernel? I have some header files in a directory, and would like to include the path to that directory in the list of all directories searched. How may I do that? I tried exporting C_INCLUDE_PATH, but that doesn't remove the error, which says that it still can't find the header file.
Thanks,
D.
There is generally no environment variable that lists all of the directories searched for header files. The directories searched are a function of the compiler used. Your compiler almost certainly has a command-line switch to add a directory to the search list. E.g., for GCC and clang, consider the “-I” switch and related switches. Your compiler may also have environment variables where you can list directories to be added to the search list, such as C_INCLUDE_PATH. Keep in mind these likely list additional directories to search; they do not list all the directories searched.
Add -I/where/ever arguments to EXTRA_CFLAGS in your Makefile. Though generally this kind of thing is bad form. The kernel build includes its own include tree (and the local directory, of course). Is there a reason your code can't conform to the existing framework?

How to define relative paths in Visual Studio Project?

I have a library and a console application that uses a library. The library has a folder with source and header files.
My project is in a child/inner directory but that library directory that I want to include is in a parent/upper directory.
My project directory:
H:\Gmail_04\gsasl-1.0\lib\libgsaslMain
Includes files are here:
H:\Gmail_04\gsasl-1.0\src
How can I use paths relative to the project directory, to include folders that are in a parent/upper directory?
Instead of using relative paths, you could also use the predefined macros of VS to achieve this.
$(ProjectDir) points to the directory of your .vcproj file, $(SolutionDir) is the directory of the .sln file.
You get a list of available macros when opening a project, go to
Properties → Configuration Properties → C/C++ → General
and hit the three dots:
In the upcoming dialog, hit Macros to see the macros that are predefined by the Studio (consult MSDN for their meaning):
You can use the Macros by typing $(MACRO_NAME) (note the $ and the round brackets).
If I get you right, you need ..\..\src
I have used a syntax like this before:
$(ProjectDir)..\headers
or
..\headers
As other have pointed out, the starting directory is the one your project file is in(vcproj or vcxproj), not where your main code is located.
By default, all paths you define will be relative. The question is: relative to what? There are several options:
Specifying a file or a path with nothing before it. For example: "mylib.lib". In that case, the file will be searched at the Output Directory.
If you add "..\", the path will be calculated from the actual path where the .sln file resides.
Please note that following a macro such as $(SolutionDir) there is no need to add a backward slash "\". Just use $(SolutionDir)mylibdir\mylib.lib.
In case you just can't get it to work, open the project file externally from Notepad and check it.
There are a couple of hints you need to know.
consider your app is running under c:\MyRepository\MyApp
a single dot on your path means the folder where your app runs. So if you like to reach some folder or file under MyApp folder (imagine c:\MyRepository\MyApp\Resources\someText.txt) you can do it like var bla = File.Exists(./Resources/someText.txt)
and you can go one level up with double dots (..) think about a folder under c:\MyRepository\SomeFolder\sometext.txt
for MyApp, it will be like
var bla = File.Exists(../SomeFolder/someText.txt)
and it is possible to go 2,3,4.. levels up like
../../SomeFolder (2 levels up)
../../../SomeFolder (3 levels up)
and path starting with no dots means the drive root. var bla = File.Exists(/SomeFolder/someText.txt) will look for the c:\SomeFolder\someText.txt in our scenario.

How to tell the preprocessor to search for a particular folder for header files, when I say #include <xyz.h>

I have around 120 header files (.h files) , and in all of them each one includes many other header files using #include <abcd/xyz.h>, but as I kept .h files in a specific folder, preprocessor is generating filenotfound error.
I moved all the .h files to the single .C file that is calling the first headerfile.
One way to do is make #include <abcd/xyz.h> as #include "abcd/xyz" , but I need to do this in all the header files wherever there is an include statement, and there are hundreds of them.
I can't include many of them in the headerfiles section in Visualstudio because, some of the headerfiles have the same name, but they reside in different directories. (<abcd/xyz.h>,<efgh/xyz.h>).
Any way to do this?
You should add a path into "Additional include directories" in the "C++" section of the project options (the "General" tab). You can use environment variables as well as "this folder" (.) shortcut and "up one folder" (..) shortcut for this setting to not be bound to a certain directory structure.
and I can't include many of them in the headerfiles section in Visualstudio because , some of the headerfiles have the same name, but they reside in different directories.(,)
That's a pretty big problem unless the files that are including those non-uniquely named headers are in the same directory as the header files themselves.
You have no way to guarantee that the compiler will locate one header before another without modifying the #include directive itself (and adding a relative path as one example).
EDIT: It looks like Visual Studio will allow you to specify different Additional Include Directories for each source file in a project (rt-click on the source file in Solution Explorer and modify C/C++ properties). But I think this would be more work than modifying the #include directives themselves - depends on how many non-unique header filenames you have.
In the project settings (under C/C++ in VS2005/2008) there's an option for "additional include directories". You can add the folders containing your header files here, using relative paths.
You can also do this at the IDE level in Tools -> Options -> Projects and Solutions -> VC++ Directories -> Include Files. Typically this method is reserved for headers included as part of a formal library. The first option is typically preferred as it's portable (you can ship your project file to another developer and, provided you use relative/macro'd paths, they can build the project as-is).
What you're looking for is the -I flag and you give the directory...
If you have a Makefile, you should add it to the CPP_FLAGS something like that....
You can also add an INCLUDE variable to your environment variables.

Resources