How do I save preprocessor output using the Dev-C++ IDE? - ide

I'd like to be able to view preprocessor output in order to make sure my preprocessor directives run correctly. Dev-C++ has an option in Tools > Compiler Options... > General to add commands when calling the compiler, and I've added the command -E C:\Personal\preprocessed.cpp. I got a compiler error saying the file didn't exist, but shouldn't the compiler just create the file in that case? I created the file, and now I'm getting this error: cannot specify -o with -c, -S or -E with multiple files.
Why am I using Dev-C++ instead of Visual Studio? Since I'm still learning, I'd like to be able to test just a few lines of code without having to create an entire new project.
Yes, I've seen this question and no adequate answer was given. Please don't mark this as a duplicate.
Thanks in advance for your help!

I've added the command -E C:\Personal\preprocessed.cpp. I got a compiler error saying the file
didn't exist, but shouldn't the compiler just create the file in that case?
No, because the -E option
takes no argument, filename or otherwise. It simply instructs the
compiler to do nothing but preprocessing. The preprocessed code is written to the standard output. Thus:
Thus:
g++ -E C:\Personal\preprocessed.cpp foo.cpp
tells the compiler that you want run g++ -E with the pair of input files C:\Personal\preprocessed.cpp and foo.cpp,
which as you've discovered is not allowed.
The simple thing that you want to do is absurdly difficult with your IDE of choice. Assuming
the source file you want to preprocess is C:\Personal\foo.cpp and the g++ is in your PATH,
just open a command window in C:\Personal and run:
g++ -E foo.cpp > foo.ii
I suggest the output file foo.ii - though you can call it whatever you like - because g++ recognizes the extension .ii as denoting C++ source code that has already been preprocessed. You can run:
g++ -Wall -o prog foo.ii
and foo.ii will be compiled and linked as program prog without being preprocessed again.

Related

CMake's add_custom_command doesnt trigger rebuild of library

Iam using CMake together with ninja to build a library. The library is depending on some code which may be generated before-hand by a custom command. The source for this code is within the source-tree and it must stay there, I have no freedom here.
Here's my CMake code:
add_library(some_lib some_source.c)
#some_source.c may be modified by the following custom command
add_custom_command(
COMMAND codegen.exe -i some_input.xml
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/generated"
OUTPUT ${CMAKE_BINARY_DIR}/generated
DEPENDS some_input.xml
COMMENT "Generating code ..."
)
add_custom_target(generate_something DEPENDS ${CMAKE_BINARY_DIR}/generated)
add_dependencies(some_lib generate_something)
Now if some_input.xml is changed I want to also rebuild some_lib. However in practice this code doesnt seem to work, the command is executed but after it is executed some_lib is not beeing rebuild, though the timestamps of the output files (some_source.c) of the custom command are newer than the library.
Can someone give me a hint on what am I doing wrong or how I can achieve this? Or is there a problem with CMake and ninja?
Thanks in advance, if you need more information please let me know.
Steve
[edit:]
It seems to be caused by the generator tool, when I use the BYPRODUCTS option of add_custom_command and replace the generator tool invocation by a cmake -E touch command on some_source.c everything works as expected. Can someone give me a hint on how to debug this, why ninja cancels the build after the generator tool has finished?
Thanks, Steve
[edit2]
I found the problem, the problem was that the codegen.exe tool was generating not only one source file but several into an output folder. I need to specify all of these potentially modified sources to as "BYPRODUCTS". Than everything works as expected.
I dont want CMake to delete the file if a "clean" is executed
BYPRODUCTS will still be cleaned.
What can be done is to utilize a dependency tracking file like you've shown (the "${CMAKE_BINARY_DIR}/generated", I used *.stamp) and then add the dependency tracking file as an OBJECT_DEPENDS to some_source.c
This only works if some_source.c is pre-existing. Initial testing had some_source.c get cleaned if I tried to add the GENERATED property.
cmake_minimum_required(VERSION 3.18)
project(in_source_generated)
add_library(some_lib some_source.c)
#some_source.c may be modified by the following custom command
add_custom_command(
# This is the command that actually generates the in source code file.
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/some_input.c ${CMAKE_CURRENT_LIST_DIR}/some_source.c
# This command generates a stamp file which is used as the dependency
# tracking
COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/some_source.stamp"
OUTPUT ${CMAKE_BINARY_DIR}/some_source.stamp
DEPENDS some_input.c
COMMENT "Generating code ..."
)
add_custom_target(generate_something DEPENDS ${CMAKE_BINARY_DIR}/some_source.stamp)
add_dependencies(some_lib generate_something)
set_source_files_properties(some_source.c PROPERTIES OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/some_source.stamp)
add_executable(main main.c)
target_link_libraries(main PRIVATE some_lib)
A simple main.c
#include <stdio.h>
int get_value();
int main(int argc, char *argv[]) {
printf("The value is %d.", get_value());
}
some_source.c and some_input.c have the same content. Just toggled the return value in some_input.c to test out.
int get_value(){
return 4;
}

CMake add_custom_command runs everytime

I am using a custom command for generating C++ Lexers and Parsers from ANTLR4 grammars. Right now I have the following:
set(MY_PARSER_INC
${PROJECT_SOURCE_DIR}/Headers/MyParser/MyLexer.h
${PROJECT_SOURCE_DIR}/Headers/MyParser/MyParser.h
${PROJECT_SOURCE_DIR}/Headers/MyParser/MyParserBaseVisitor.h
${PROJECT_SOURCE_DIR}/Headers/MyParser/MyParserVisitor.h
)
set(MY_PARSER_SRC
${PROJECT_SOURCE_DIR}/Sources/MyParser/MyLexer.cpp
${PROJECT_SOURCE_DIR}/Sources/MyParser/MyParser.cpp
)
add_custom_command(
OUTPUT ${MY_PARSER_INC} ${MY_PARSER_SRC}
DEPENDS ${PROJECT_SOURCE_DIR}/Grammars/MyGrammar.g4
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/Headers/MyParser/
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_SOURCE_DIR}/Sources/MyParser/
COMMAND java -cp "${ANTLR_CLASSPATH}" "org.antlr.v4.Tool" -Dlanguage=Cpp -visitor -no-listener -package MY::NESTED::NAMESPACE -encoding iso-8859-1 -o ${PROJECT_SOURCE_DIR}/Sources/MyParser/ ${PROJECT_SOURCE_DIR}/Grammars/MyGrammar.g4
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/Sources/MyParser/*.h ${PROJECT_SOURCE_DIR}/Headers/MyParser/
COMMAND ${CMAKE_COMMAND} -E remove -f ${PROJECT_SOURCE_DIR}/Sources/MyParser/*.h
COMMENT "generating sources for My Parser"
)
and then I use the output files in my add_library command to maintain the dependency.
This does exactly what I expect it to do. It creates the lexers and parsers correctly. It maintains the dependency between those sources and the target library also correctly. Only one problem: It runs every time! Even when the grammar file has not been modified (I checked the file date on the grammar and generated lexers/parsers to be sure)! I have seen some similar questions online but still can't figure out why this is happening.
Any clue?!
EDIT1:
Adding more info, since it may still be unclear.
After the add_custom_command I have the following:
include_directories(${PROJECT_SOURCE_DIR}/Headers/MyParser/)
add_library(MyLibrary SHARED
${MY_PARSER_INC} ${MY_PARSER_SRC}
other_files.hpp other_files.cpp)
which I assume creates a direct dependency between the generated source files and my target library.
Here's my guess.
You need to make a custom target.
https://cmake.org/cmake/help/latest/command/add_custom_target.html?highlight=custom_target
add_custom_target(custom_target_create_parser_code DEPENDS
${MY_PARSER_INC} ${MY_PARSER_SRC}
)
This will make a target that depends on the custom command you wrote.
Now cmake has something to attach your command to.
Now you need to add the dependency to your static library you mentioned.
https://cmake.org/cmake/help/latest/command/add_dependencies.html
add_dependency(your_static_library custom_target_create_parser_code)
Now cmake shouldn't re-run your custom command code everytime.
EDIT BTW:
Craig Scott's book actually has a subchapter devoted to this topic:
https://crascit.com/professional-cmake/
Chapter 18 Custom Targets
Chapter 18.3 Commands That Generate Files
EDIT #2:
If all else fails try the official cmake discourse:
https://discourse.cmake.org/
Your question is well formed and cmake developers look their for questions.
So you should get an answer.

g++ in cygwin doesn't create .exe file

I just installed cygwin on a new Windows box running Windows 7 and I am getting funny behavior when I compile a c++ program. Here's what I type:
g++ test.gpp -o test
On my other Windows boxes, this creates an exe file, test.exe, and it is, of course an executable. But on this installation, the file test is created. To my surprise, it is not an executable, but rather looks like a debug file (in ascii printables). If I instead type:
g++ test.gpp -o test.exe
Then I do get the executable test.exe. (1) why in all my other implementations do I get the executable, but not with this most recent attempt? (2) Why do I care? Well, I also work on linux boxes and am not accustomed to typing the extension ".exe". (I hate that aspect of non-linux files!) I am guessing that there is some sort of one-time flag I can set to make the default file that g++ creates be a .exe file.
The problem with this problem is that none of you may be able to reproduce it! (I can't on my other machines!)
As far as I can tell, g++ doesn't recognize the .gpp extension. Rename the file from test.gpp to test.cpp and try again.
On my Cygwin system, g++ test.gpp gives me an error message:
... file format not recognized; treating as linker script ...
Cygwin compilers do create executable files with a .exe extension (because Windows requires it), but it also lets you refer to such files without the suffix. So, for example:
ls -l test.exe
and
ls -l test
should both show you the same file. (If you happen to have files with both names, things can get a bit confusing -- so don't do that.) g++'s -s option also treats the .exe suffix specially, so -o test and -o test.exe should do the same thing.
I don't know why you're seeing the behavior you describe. Perhaps you happen to have something in test.gpp that looks like a valid linker script?
g++ test.gpp -o test
This should create a file called test (with no extension). If that file is created than give executable permission the file using chmod +x test
than use ./test to run it. see if it works.

No targets specified and no makefile found

I have a make file that contains this code:
all: main.o Etudiant.o
gcc -lobjc -o program main.o Etudiant.o
main.o:main.m Etudiant.h
gcc -c main.m
Etudiant.o:Etudiant.m Etudiant.h
gcc -c Etudiant.m
When I write this in the shell command:
$make
I got this:
make: **** No targets specified and no makefile found. Stop.
How do I fix this?
Mmm... makefiles. Whee.
All that whitespace at the beginning of the line. That has to be tabs. Or Make will barf up a really obscure error. Make sure those are tabs and try again.
See the button on the left side of the keyboard labeled "tab". Delete the spaces and hit that once to insert a tab character.
Try make all. IIRC (been a few years since I've had to muck with makefiles) most makes will default to all, but maybe yours isn't.
Extension doesn't matter.
Holy Heck! We are all Extra Dense(#bbum mostly so)!
"no Makefile found" means... well.. that Make didn't even see the makefile. The suggestions to rename the Makefile.m to Makefile are correct. As well, the whole tab vs. whitespace thing is certainly pertinent.
and no makefile found
If you just type make with no arguments or make all, make will look for a file called Makefile in the current directory. If it's not there, you get the error you saw. make will not look in subdirectories for Makefile nor will it accept a file called Makefile.m.
In my case, the my makefile had the name MakeFile, changing it to Makefile worked
Re:
$ Make
Make: * No targets specified and no makefile found. Stop.
I just had this error and found that the Makefile extension (none) had been converted to .bat somewhere along the line.
Just spent a few insanely frustrating moments with this error. My mistake was not all that subtle: I titled the makefile MakeFile not Makefile, so even using the -f Makefile command (forcing the makefile name) still resulted in not-found, because it was MakeFile, not Makefile.

Invoke OCaml compiler to just produce .cmi

maybe I'm just failing in a really simple thing but I'm developing an intepreter written in OCaml with standard tools as ocamllex and ocamlyacc and I have this situation:
iparser.mly contains parser spec
ilexer.mll contains lexer spec
impossible.ml contains the vm that executes the code and all the types needed
The instruction type that defines various instructions is in impossible.ml and it is needed by the parser but impossible.ml uses the parser defined in iparser.mly so they both need each other to compile correctly.
Is there a way to produce just the .cmi file for my impossible.ml? In this way the parser would know about types defined in impossible.ml and it will allow me to compile impossible.cmo/.cmi and later compile also impossible.cmo. Then I can link all of them together.
So far my compiling script is:
ocamlyacc iparser.mly
ocamlc -c iparser.mli
ocamllex ilexer.mll
ocamlc -c ilexer.ml
ocamlc -c iparser.ml
ocamlc -c impossible.ml
ocamlc -o imp.exe ilexer.cmo iparser.cmo impossible.cmo
but this doesn't work because ocamlc -c iparser.ml needs at least impossible.cmi to know the types.
Any suggestions? Thanks in advance..
You need to create an impossible.mli and compile that. That will produce the impossible.cmi and only the .cmi.
Alternatively:
ocamlc -i impossible.ml
will print the mli to stdout. You could do something like this:
ocamlc -i impossible.ml > impossible.mli
ocamlc -c impossible.mli
IMHO, you cannot legitimately compile recursively-dependant modules this way. Either factor out the interdependencies in the third module (usually easy), or pass them as parameters (or mutable initialization references - ugly), or use recursive modules.