I have a rather long list of preprocessor definitions that I want to make available to several C programs that are compiled with gcc.
Basically I could create a huge list of -DDEF1=1 -DDEF2=2 ... options to pass to gcc, but that would create a huge mess, is hard to use in a versioning-system and may at some time in the future break the command line length limit.
I would like to define my defines in a file.
Basically the -imacros would do what I want except that it only passes it to the first source file: (below from the gcc documentation):
-include file Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched
for file is the preprocessor's working directory instead of the
directory containing the main source file. If not found there, it is
searched for in the remainder of the #include "..." search chain as
normal. If multiple -include options are given, the files are included
in the order they appear on the command line.
-imacros file Exactly like -include, except that any output produced by scanning file is thrown away. Macros it defines remain defined.
This allows you to acquire all the macros from a header without also
processing its declarations. All files specified by -imacros are
processed before all files specified by -include.
I need to have the definitions available in all source files, not just the first one.
Look at the bottom of this reference.
What you might want is the #file option. This option tells GCC to use file for command-line options. This file can of course contain preprocessor defines.
Honestly - it sounds like you need to do a bit more in your build environment.
For example, one suggestion is that it sounds like you should create a header file that is included by all your source files and #define all your definitions.
You could also use -include, but specify an explicit path - which should be determined in your Makefile/build environment.
The -imacros would work, if your Makefile were building each source file independently, into its own object file (which is typical). Its sounds like you're just throwing all the sources into building a single object.
Related
i'm working on a project requiring cmake. i'd like to add some custom rules to my makefile, but can't quite get my head around how to do it.
both c source files and header files are in the same directory. also in this same directory are a number of .def files, which are the sources for some of the header files #included in the source during compilation.
if i were to do this in a makefile, i'd use a simple rule like
.SUFFIXES: .def
.def.h:
$(PREPROC) $< > $#
how can i do this with cmake ??
i've tried various permutations of the following, both with and without cmake working directory specifications :
add_custom_command(
OUTPUT vvr_const.h
PRE_BUILD
COMMAND preproc vvr_const.def > vvr_const.h
DEPENDS vvr_const.def
)
add_custom_target(vvr_const.h DEPENDS vvr_const.def)
but the header file isn't generated by the time the c source file is compiled, so the compile fails. i've also tried a variation where i replace the last line above with
set_property(SOURCE main.c APPEND PROPERTY OBJECT_DEPENDS vvr_const.h)
in this case, the header file is correctly generated in advance, but make can't find it, and complains that there's no rule to make the target .h.
ideally this would be a general rule, like the make rule above, but i'm not opposed to making a separate rule for each of the .def files if that's what it takes.
cheers.
There are 2 problems with the add_custom_command approach you present:
You did not specify a working directory; by default the command is run in the build directory, not in the source directory.
You rely on shell functionality here (the redirect to a file). Even though this probably still works. You should go with an approach that does not rely on the shell.
To solve issues 1 and 2 I recommend creating a seperate cmake script file receiving the absolute paths to input and output files and using those in the custom command. This allows you to use execute_process to specify the file to write without relying on the platform.
preprocess_def.cmake
# preprocess def file
# parameters INPUT_FILE and OUTPUT_FILE denote the file to use as source
# and the file to write the results to respectively
# use preproc tool to get data to write to the output file
execute_process(COMMAND preproc "${INPUT_FILE}"
RESULT_VARIABLE _EXIT_CODE
OUTPUT_FILE "${OUTPUT_FILE}")
if (_EXIT_CODE)
message(FATAL_ERROR "An error occured when preprocessing the file ${INPUT_FILE}")
endif()
CMakeLists.txt
set(_INPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.def")
set(_OUTPUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vvr_const.h")
# not necessary to use build event here, if we mark the output file as generated
add_custom_command(OUTPUT "${_OUTPUT_FILE}"
COMMAND "${CMAKE_BUILD_TOOL}" -D "OUPUT_FILE=${_OUTPUT_FILE}" -D "INPUT_FILE=${_INPUT_FILE}" -P "${CMAKE_CURRENT_SOURCE_DIR}/preprocess_def.cmake"
DEPENDS "${_INPUT_FILE}")
add_executable(my_target vvr_const.h ...)
set_source_files_properties(vvr_const.h PROPERTIES GENERATED 1)
Documentation from cmake:
PRE_BUILD
On Visual Studio Generators, run before any other rules are executed within the target. On other generators, run just before PRE_LINK commands.
So possibly your command is just running too late.
I'm using GNU Make 4.0 to compile objects on an IBM i. Most items are ok and conflict-free (.c compiles to a .module, .pf compiles to a .file), but a couple types of items use the same filename suffix for both source and object. For example, commands end in .cmd for the source code and also for the compiled command object. This results in a makefile definition like this:
C_CODE1.MODULE: C_CODE1.C # This is ok -- no conflict
COMMAND1.CMD: COMMAND1.CMD # Error! Make thinks it's a circular dependency.
What can be done to tell Make that the .cmd item on the left and the one on the right are actually two different items? The object suffixes are fixed by the operating system and cannot be changed. The source code suffixes could be changed, but then they wouldn't appear correctly in our code editors without customization. The source code does exist in a separate directory from the objects, but paths aren't really specified in the makefile, other than when setting up VPATH.
If the target name does not have to match the prerequisites, I would change the target name to something else, for example COMMAND1: COMMAND1.CMD.
If they have to be matched then I would write like the following to add the extension explicitly in the recipe.
COMMAND1 : COMMAND1.CMD
cat $< > ${#}.CMD
For the source, even if you are using traditional source files, it's not necessary to use the standard source member type. You could use say CMDSRC for the source member type of your command source.
When a file contains an include line like this:
#include "name.h"
gcc (and other C compilers) search for the file "name.h" in the directory containing the file being compiled. This does not by default happen if the line looks like this:
#include <name.h>
Is there an option to gcc to make it behave this way in the latter case too? As noted in the gcc documentation, "-I. searches the compiler's current working directory for header files. That may or may not be the same as the directory containing the current file." In the case I am working on (importing external code that used a build environment that automatically added the containing directory to the search path into a system that doesn't have such a build facility), the current directory is unfortunately not the same. What can I do? I'd rather not have to specifically modify the files...
Say I have a header file which is included by many source files, maybe with a very deep hierarchy. It is very boring to list this common header file in the prerequisites of each source object, and not sure whether there is an elegant solution. Thanks!
You can generate such dependencies with gcc -M. From TFM:
-M Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from -include or -imacros command line options.
Also see Generating Prerequisites Automatically.
I know some linkers have a limit of how many object files are allowed on the command line. What is Visual Studio's? Also, if you exceed this number, some linkers allow you to specify a file containing the name of all the object files, and you would only pass that as an argument. Here's an example to show you what I mean:
some_linker file1.o file2.o ... file9000.o -out=some.lib
Suppose 9000 is too much for this linker, but it allows you to write the path to the objects in another file, example.txt:
file1.o
file2.o
...
file9000.o
And the linker call becomes:
some_linker -input=example.txt -out=some.lib
How is Visual Studio behaving in this situation? Does it allow for something like this?
The maximum number of arguments doesn't appear to be specified in that portion of the documentation. I'm not sure if this is provided elsewhere, but I personally haven't seen it.
However, link.exe does allow you to specify a text file containing the name of all the object files, which it calls a "command file". According to the documentation, you specify a command file by prepending its filename with an at sign:
LINK #commandfile
The arguments in the command file can be separated by either spaces or tabs (as on the command line) and by newline characters.