I know VSCode is positioned this way in the market, probably to differentiate it from VS. And I switched to it from a much less “smart” editor (TextMate, which I still adore! No offense meant to TM creator/maintainers!).
I’m having a hard time seeing this as a clear distinction, however. I mean, VSCode has a built in debugger/protocol, language server/protocol/intellisense, file system aware refactoring, code rewriting refactoring, integrated git client, inline blame and history navigation, GitHub integration, linter integration including automated fixes…
I understand it’s a different tool than VS, but I honestly don’t have a clear understanding of what separates editor from IDE in this case.
Anything lesser, they're calling a simple code editor but, by actual definition, they are referring to a lighter IDE (as the ones that can be installed as base editors they have all extended with plugins/extensions to that point) and then acting like the topic is about the big-brand IDEs, even though it is making points against tooling they are all using with their "editors" just like what you're using VSCode for.
Therefore, if you want you can invoke from inside the editor any commands needed for project management or for compiling/linking/running/debugging.
So in the end you are right that a powerful editor can do what an IDE does, after some customization.
The main difference with IDE's is that the project management provided by the IDE is normally non-optional, you are forced to always use it.
In 30 years of experiencing a very large number of IDE's I have not seen even a single one where using its project management functions would not waste a lot of time comparing to non-integrated alternatives.
I think that it is sad that only a very small number of developers know how to use correctly the ancient program "make". I do not know why this happened. To use correctly "make" I have never needed anything else besides reading the GNU make manual provided with gmake, but it seems that very few people read the manual.
The only time when I had to write makefiles was more than 20 years ago, when I have written a set of universal makefiles, which I have been using unchanged for every software project ever since. For any new project I need to just (optionally) add a file with some extra definitions, e.g. a list of directories where the source files are located or the names of the executables or libraries that must be built. If no definitions are provided, suitable defaults are used, e.g. the directory with the Makefile also contains the source files and the target is an executable with the same name as the directory. The Makefile per target directory may contain just a single line, with an include directive for the universal makefile. The universal makefile searches all the source directories for all the possible types of source files, selects automatically the appropriate compilers based on the language indicated by the file name extensions and on the cross-compilation target if one is specified, generates automatically all the dependencies and so on.
Instead of using "make" like this, almost all the open-source projects that I have seen have huge and immensely complicated makefiles that are much more difficult to read, understand and modify than the source files of the programs. When the makefiles are generated from templates, those are typically even more difficult to understand and modify.
I have no idea who loves those extremely complex methods of compiling and building software projects.
During the years, a lot of replacements for "make" have been introduced, which are better than "make" used wrongly, but I have not seen any which is better than "make" used rightly, without pointless complications.
For easy maintenance, the universal makefile is split into 4 files that are completely universal + 1 makefile with extra definitions per each combination of operating system and CPU type that might be a target for compilation.
The extra files for specific compilation targets, e.g. skylake-linux-gnu, armv7e-m4-none-eabi, i686-cygwin and so on, contain definitions for the names of all the tools that might be used, e.g. compilers for various programming languages, linking commands, librarian commands, binary file modification commands (e.g. objcopy), default locations for library files, default locations for include files, default values for compilation flags.
The 4 completely universal files do not contain directly any command name or command flags or any file name or any directory name. They contain only variable names whose values are either defined in the operating system/CPU specific makefile or whose values are determined by the make command by scanning the project and by transforming the found files, e.g. by replacing the file name extensions.
The 4 completely universal files are:
1. A file for the top directory of a complex project, which descends recursively in all subdirectories and runs there the given make command, if a Makefile exists in the subdirectory
2. A file with make targets. Examples of make targets:
clean:
$(RM) $(RMFLAGS) $(MAP) $(BIN) $(IMPLIB) $(EXE) $(LIB) $(WEXE) $(DLIB)
$(RM) $(RMFLAGS) $(OBJS) $(OBJS:.o=.d) $(OBJS:.o=.lst)
and
all : $(EXE) $(LIB) $(WEXE) $(DLIB)
The 4 variables above are the files to be built, respectively CLI executables, static libraries, GUI executables and dynamic libraries.
As I have said everything must be expressed using variables that will be defined elsewhere.
3. A file with make rules, for how to build any kind of file that might be encountered. Examples of rules:
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ -c $<
%.s: %.cpp
$(CXX) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -o $@ -S $<
%.d: %.cpp
$(CXX) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -MD -o $(@:.d=.o) -c $<
4. A file with definitions, which is the most important in simplifying the makefiles needed for any new project, which are typically almost empty, because they do not need any other line besides including the universal makefile, even if I usually add a definition with a list of source directories, in order to separate the place where the project is built from the place where the source files are stored and possibly some options, e.g. building a debug version instead of a release version, or building for a cross-compilation target.
Example how to determine the directories with source files:
ifeq "$(strip $(SOURCE_DIRS))" ""
SOURCE_DIRS := .
endif
ifeq "$(strip $(PREFIX_DIR))" ""
VPATH := $(SOURCE_DIRS)
else
VPATH := $(addprefix $(PREFIX_DIR)/, $(SOURCE_DIRS))
endif
Example of how to scan the source directories for source files written in a certain programming language:
CPP_FILES := $(notdir $(wildcard $(addsuffix /*.cpp, $(VPATH))))
The list for every kind of source files is stored in a corresponding variable like above.
For the source files that are compiled to object files, the list of object files that must be made is computed so:
OBJS := $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o) $(SS_FILES:.S=.o) $(S_FILES:.s=.o) $(O_FILES)
I use many more kinds of source files, so the OBJS above is just a shortened example.
The operating system/CPU type specific makefile includes the 3 universal files with targets, rules and definitions and it also includes the automatically generated dependencies:
include $(OBJS:.o=.d)
so later only the specific makefile needs to be included, depending on the compilation target.
There are many more details, but these are the general principles. They are intended to make me write as little as possible in the Makefile for a new project.
If I do not define in the Makefile from the project directory what shall be built with "make all", then either an executable is built, having the same name as the Makefile directory, or another kind of file is built, if the directory has a special suffix, e.g. a static library for a directory ending in "_lib".
When I add, delete, move or rename source files, I do not have to do anything for project management, except doing a "make clean" before that, because the next "make" will update the lists of source files.
- Checking sources out of version control
- "Importing" them in the Eclipse workspace as projects from existing code in an arbitrary location
- Configuring what Maven installation, and with what configuration files, is to be used to build your projects
- Defining a grimoire of Maven command lines (build and test locally, build and deploy somewhere else, package for release, etc.) as run/debug configurations
The impact is limited to harmless project metadata files (containing nothing important that isn't mirrored from Maven POM files) and repeating in the closed world of Eclipse options configurations, paths etc. that are probably already in scripts, CI pipeline definitions and so on.The tooling and layout of the same functionality you choose to use is something more modern tools, and product versions, have improved upon but is unrelated to what an IDE is. It also differs between tools and IDEs. For you to say you've never used an IDE with simple or fast file handling is either a lie or a severe lack of experience, as almost all decent ones have a 1 or 2-click approach via the explorer (and toolbar/hotkeys if you don't like an explorer side-pane). I actually can't think of any half-decent IDE that doesn't have the same approach for files as popular code editors, and I've used a lot of both for different platforms and languages. The only time I've had noticeable experiences is in cases via command/terminal but we're talking GUI editors here.
Worth noting, I have never in my career found myself mentioning any Eclipse-based IDE as an example of a good IDE. In fact, almost every dev I've ever met regards them as the worst IDEs they have experienced, not as a baseline standard for or expectation of IDEs. It's basically redundant to comment on x experience being bad as anyone that has ever used one already knows that is expected.
For editing or just navigating the source files, the smarter the editor is, the better.
On the other hand I have never seen any IDE where the management of projects (e.g. adding/deleting/moving/renaming files and setting compilation/linking options) and the compilation/building/running functions are as simple and fast as how that can be done without using an IDE (if you know how to do it in the right way).
Especially the Eclipse-based IDE's provided by many vendors of embedded products are the worst offenders.
I have wasted too much time with helping puzzled coworkers to find where in the hierarchy of IDE menus one could find whatever was needed. Even when knowing where to find the commands, using the IDE menus was many orders of magnitude slower than what I could do outside the IDE to perform the same function upon the project.