Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 335175 - Incorrect makefile for project with multiple source files with the same name and path and different extensions
Summary: Incorrect makefile for project with multiple source files with the same name ...
Status: NEW
Alias: None
Product: CDT
Classification: Tools
Component: cdt-build-managed (show other bugs)
Version: 8.0   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact: Jonah Graham CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-01-24 06:32 EST by Alex Freidin CLA
Modified: 2020-09-04 15:26 EDT (History)
2 users (show)

See Also:


Attachments
Example project (4.68 KB, application/zip)
2011-01-24 06:34 EST, Alex Freidin CLA
no flags Details
Diff patch (1.09 KB, text/plain)
2012-03-07 07:17 EST, Alex Freidin CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Freidin CLA 2011-01-24 06:32:08 EST
Build Identifier: 20100917-0705

A project may include the same files names but with different extensions, e.g. .c, .cpp, .s. The case when more than one file is being compiled is described in bug 185671. 
This case is when only one of the files is "active" and another is excluded from build. For example, code that started as C and then enhanced to C++ or optimized into assembly. It is common to keep the original C source in the project as reference and exclude it from build. In such project, if the Internal Builder is used, the build is done correctly. If the makefile builder is used, then sometimes an excluded file is built instead of the "active" one.

Steps to reproduce (reproducible in CDT 7.0.1):
1. Create Hello World C++ template project named HelloCPP
2. Add file.cpp and file.c
3. Exclude file.cpp from build
4. Make sure "External Builder" is selected at Project>Properties>C/C++ Build>Builder Settings>Builder type.
5. Build the project, observe that file.cpp is built instead of file.c

The reason for the bug is in the makefile generation. The subdir.mk has a list of objects in $(OBJECTS) variable. It then matches them with the rules:

src/%.o: ../src/%.cpp

src/%.o: ../src/%.c

If the CPP rule appears first in the makefile, then for file.o, the makefile matches file.cpp, even if it is excluded from build. So, the correct file.c is never compiled. Note that the rules order is undefined and changes depending on the file names in the source directory. That's why sometimes everything works OK and sometimes it doesn't.

To build projects properly, the rules should be enhanced to relate to the relevant objects, e.g. 

$(C_OBJS): src/%.o: ../src/%.c
$(CPP_OBJS): src/%.o: ../src/%.cpp

The variables C_OBJS and CPP_OBJS can be initialized directly like $(OBJECTS) or be derived i.e.: C_OBJS = $(C_SRCS:../src/%.c=src/%.o)

Reproducible: Always
Comment 1 Alex Freidin CLA 2011-01-24 06:34:36 EST
Created attachment 187411 [details]
Example project
Comment 2 Alex Freidin CLA 2012-03-06 17:40:03 EST
The pattern rules can be enhanced in the following manner, without adding new variables.
Suppose we have a generated rule: 
tests/%.o: ../tests/%.cpp

The following appends a list of all relevant "tests/*.o" files to the rule, eliminating those that are not in CPP_SRCS:

$(patsubst ../tests/%.cpp, tests/%.o, $(filter $(wildcard ../tests/*.cpp), $(CPP_SRCS))) : \
tests/%.o: ../tests/%.cpp
Comment 3 Alex Freidin CLA 2012-03-07 07:17:13 EST
Created attachment 212200 [details]
Diff patch

I used the attached patch to add the above rule to the makefile (need to convert it to GIT patch).